﻿<template>
  <component v-if="iconComponent" :is="iconComponent" v-bind="$attrs" :class="iconClass" />
  <div v-else-if="loading" class="icon-loading" :class="iconClass">
    <div class="loading-placeholder"></div>
  </div>
  <div v-else class="icon-error" :class="iconClass">?</div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from "vue";
import { iconManager } from "@/utils/ui/icons";

/**
 * 动态图标组件
 * 支持按需加载Element Plus图标
 */

const props = defineProps({
  // 图标名称
  name: {
    type: String,
    required: true,
  },
  // 图标大小
  size: {
    type: [String, Number],
    default: "",
  },
  // 图标颜色
  color: {
    type: String,
    default: "",
  },
  // 是否预加载
  preload: {
    type: Boolean,
    default: false,
  },
  // 加载失败时的降级图标
  fallback: {
    type: String,
    default: "",
  },
});

const iconComponent = ref(null);
const loading = ref(false);
const error = ref(false);

// 计算图标样式类
const iconClass = computed(() => {
  const classes = ["dynamic-icon"];

  if (props.size) {
    classes.push(`icon-size-${props.size}`);
  }

  if (props.color) {
    classes.push(`icon-color-${props.color}`);
  }

  if (loading.value) {
    classes.push("icon-loading");
  }

  if (error.value) {
    classes.push("icon-error");
  }

  return classes;
});

// 加载图标
const loadIcon = async iconName => {
  if (!iconName) return;

  try {
    loading.value = true;
    error.value = false;

    const component = await iconManager.loadIcon(iconName);

    if (component) {
      iconComponent.value = component;
    } else {
      throw new Error(`图标 ${iconName} 加载失败`);
    }
  } catch (err) {
    error.value = true;

    // 尝试加载降级图标
    if (props.fallback && props.fallback !== iconName) {
      await loadIcon(props.fallback);
    }
  } finally {
    loading.value = false;
  }
};

// 监听图标名称变化
watch(
  () => props.name,
  newName => {
    if (newName) {
      loadIcon(newName);
    }
  },
  { immediate: true }
);

// 预加载支持
onMounted(() => {
  if (props.preload && props.name) {
    iconManager.preloadIcons([props.name]);
  }
});
</script>

<style scoped>
.dynamic-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}

.icon-loading .loading-placeholder {
  width: 1em;
  height: 1em;
  border: 2px solid #e4e7ed;
  border-top: 2px solid #409eff;
  border-radius: 50%;
  animation: icon-spin 1s linear infinite;
}

.icon-error {
  color: #f56c6c;
  font-size: 0.8em;
  opacity: 0.6;
}

/* 加载动画 */
@keyframes icon-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .dynamic-icon {
    font-size: 0.9em;
  }
}
</style>
